package com.example.qxfw.dzzh.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dmgis.entity.*;
import com.example.qxfw.common.entity.yj.DzWarning;
import com.example.qxfw.common.entity.yj.YjfxdzYz;
import com.example.qxfw.common.entity.zy.BaseProduct;
import com.example.qxfw.common.service.impl.FileRequestService;
import com.example.qxfw.common.util.FileUtil;
import com.example.qxfw.dzzh.dto.AreaDto;
import com.example.qxfw.dzzh.dto.SurfaceDto;
import com.example.qxfw.dzzh.mapper.DzWarningMapper;
import com.example.qxfw.dzzh.service.DqyjService;
import com.example.qxfw.dzzh.service.YjfxdzYzService;
import com.example.qxfw.mongodb.hy.entity.HyDocFile;
import com.example.qxfw.shfx.dto.ColorAndNameDto;
import com.example.qxfw.shfx.entity.ColorAndPos;
import com.example.qxfw.ybzz.mapper.BaseProductMapper;
import com.example.qxfw.yjqx.dto.LayerRcoDto;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.ini4j.Ini;
import org.ini4j.Wini;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.example.qxfw.common.util.DmgisUtils.getCountryMap;
import static com.example.qxfw.common.util.DocxUtil.*;
import static com.example.qxfw.common.util.LayerUtil.getLayerClass;

@Slf4j
@Service
public class DqyjServiceImpl implements DqyjService {

    @Value("${dmgis.ip}")
    private String dmgisIp;

    @Value("${dmgis.port}")
    private String dmgisPort;

    @Value("${dmgis.serName}")
    private String dmgisSerName;

    @Value("${filePath.resourcePath}")
    private String resourcePath;

    @Value("${filePath.active}")
    private String active;

    @Autowired
    private YjfxdzYzService yjfxdzYzService;

    @Autowired
    private DzWarningMapper dzWarningMapper;

    @Autowired
    private BaseProductMapper baseProductMapper;


    @Qualifier("mongoSecondTemplate")
    @Autowired
    private MongoTemplate mongoTemplate;



    @Autowired
    FileRequestService ms;

    @Override
    public List getArea() throws IOException {
        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        String filePath = applicationHome.getDir().getParentFile()
                .getParentFile().getAbsolutePath() + "\\src\\main\\resources\\file";
        String fileName = "230718095334.txt";
        File file = new File(filePath,fileName);
        String jsonStr = FileUtil.readLine(file);

        ObjectMapper objectMapper = new ObjectMapper();
        List list = objectMapper.readValue(file, List.class);
        for (Object o : list) {
            JSONObject json = new JSONObject((Map<String, Object>) o);
            AreaDto area = JSON.parseObject(json.toJSONString(), AreaDto.class);
            System.out.println(area.toString());

        }
        return list;
    }

    @Override
    public List<SurfaceDto> getArea1() throws IOException {

        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        String filePath = applicationHome.getDir().getParentFile()
                .getParentFile().getAbsolutePath() + "\\src\\main\\resources\\file";
        String fileName = "230719111309.json";
        File file = new File(filePath,fileName);

        ObjectMapper objectMapper = new ObjectMapper();
        AreaDto area = objectMapper.readValue(file, AreaDto.class);
        String surfaceStr = area.getPos();
        String[] surfaceStrList = surfaceStr.split("\\*");
        List<SurfaceDto> surfaceDtoList = new ArrayList<>();
        for (String surface : surfaceStrList) {
            SurfaceDto surfaceDto = new SurfaceDto();
            String[] surfaceField = surface.split("#");
            surfaceDto.setIndex(Integer.parseInt(surfaceField[2]));
            surfaceDto.setColor("#"+Integer.toHexString(Integer.parseInt(surfaceField[0])));
            String[] points = surfaceField[1].split(",");
            double[][] range = new double[points.length][2];
            for (int i=0; i<points.length; i++){
                String[] point = points[i].split(" ");
                range[i][0] = Double.parseDouble(point[0]);
                range[i][1] = Double.parseDouble(point[1]);
            }
            surfaceDto.setRange(range);
            surfaceDtoList.add(surfaceDto);
        }

        Comparator<SurfaceDto> indexComparator = Comparator.comparing(SurfaceDto::getIndex);
        surfaceDtoList.sort(indexComparator);

        return surfaceDtoList;
    }


    @Override
    public String createTxt(String index) throws IOException {
        List<YjfxdzYz> yjfxdzYzs = yjfxdzYzService.listByIndex(index);
        File file = FileUtil.getFile("txt");

        BufferedWriter out = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file.getPath(),true)));
        out.write("[因子]"+"\n");
        for (YjfxdzYz yjfxdzYz : yjfxdzYzs) {
            out.write(yjfxdzYz.getId()+"\t"
                        + yjfxdzYz.getIndex()+"\t"
                        + yjfxdzYz.getFactorName()+"\t"
                        + yjfxdzYz.getFactorType()+"\t"
                        + yjfxdzYz.getFactorValue()+"\n");
        }
        out.close();
        return file.getPath();
    }

    @Override
    public Integer getMaxId() {
        DzWarning dzWarning = dzWarningMapper.selectOne(Wrappers.<DzWarning>lambdaQuery()
                .orderByDesc(DzWarning::getDocid)
                .last("limit 1"));
        return dzWarning == null ? 0 : dzWarning.getDocid();
    }




    @Override
    public Object createProduct(Integer issueNum, String userName, String yjType, String sXType, String date,
                                String timeChar, Integer nTimes, String colorAndPos, String posStr, MultipartFile[] images,
                                String layerName, String dlData) throws IOException, ParseException {
        //模板路径
        String templatePath;
        //产品路径
        String targetPath;
        //pdf路径
        String targetPdfPath = null;
        //配置文件路径
        String configFilePath;

        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        if (active.equals("dev")) {
            templatePath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\Documents\\风险预警模板\\地质灾害气象风险预警模板.docx";
            targetPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\temp\\地质灾害气象风险预警文档.docx";
            targetPdfPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\temp\\地质灾害气象风险预警文档.pdf";
            configFilePath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\Documents\\风险预警模板\\预警内容地灾.ini";

        } else {
            templatePath = applicationHome.getSource().getParentFile() +
                    "\\resources\\Documents\\风险预警模板\\地质灾害气象风险预警模板.docx";
            targetPath = applicationHome.getSource().getParentFile() +
                    "\\resources\\temp\\地质灾害气象风险预警文档.docx";
            targetPdfPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\temp\\地质灾害气象风险预警文档.pdf";
            configFilePath = applicationHome.getSource().getParentFile() +
                    "\\resources\\Documents\\风险预警模板\\预警内容地灾.ini";
        }

        List<DmObj> map = new ArrayList<>();
        Map<Integer, List<ColorAndNameDto>> colorAndNameMap = new HashMap<>();
        //json字符串转换为对象列表
        List<ColorAndPos> posList = JSON.parseArray(colorAndPos, ColorAndPos.class);
        //获取预警区内乡镇数据
        for (ColorAndPos typeAndPos : posList) {
            String type = typeAndPos.getColor();
            String color = "";
            switch (type) {
                case "0":
                    color = "黄色";
                    break;
                case "1":
                    color = "橙色";
                    break;
                case "2":
                    color = "红色";
                    break;
            }
            //多边形查询乡界面
            map = getCountryMap(dmgisIp,dmgisPort,dmgisSerName,typeAndPos.getPos());

            for (DmObj obj : map) {
                List<DmRcoVal> rec = obj.getRec();
                for (DmRcoVal dmRcoVal : rec) {
                    String fldName = dmRcoVal.getFldName();
                    if (fldName.toLowerCase().equals("name")) {
                        ColorAndNameDto colorAndNameDto = new ColorAndNameDto();
                        colorAndNameDto.setCounty("凌云");
                        colorAndNameDto.setCountry(dmRcoVal.getFldVal());
                        colorAndNameDto.setType(Integer.parseInt(type));
                        colorAndNameDto.setColor(color);
                        List<ColorAndNameDto> colorAndNameDtoList = null;
                        if (colorAndNameMap.containsKey(Integer.parseInt(type))) {
                            colorAndNameDtoList = colorAndNameMap.get(Integer.parseInt(type));
                        } else {
                            colorAndNameDtoList = new ArrayList<>();
                        }
                        colorAndNameDtoList.add(colorAndNameDto);
                        List<ColorAndNameDto> collect = colorAndNameDtoList.stream().distinct().collect(Collectors.toList());
                        colorAndNameMap.put(Integer.parseInt(type), collect);
                    }
                }
            }
        }

        //读取配置文件获取正文
        Wini ini = new Wini(new BufferedReader(new InputStreamReader(new FileInputStream(configFilePath), "GBK")));
        Ini.Section section = ini.get("DOCS");
        String docType = "";
        if (colorAndNameMap.containsKey(3) && !colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(0)) {
            docType = section.get("doc1");
        } else if (!colorAndNameMap.containsKey(3) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(0)) {
            docType = section.get("doc2");
        } else if (!colorAndNameMap.containsKey(3) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc3");
        } else if (colorAndNameMap.containsKey(3) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(0)) {
            docType = section.get("doc12");
        } else if (colorAndNameMap.containsKey(3) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc13");
        } else if (!colorAndNameMap.containsKey(3) && colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc23");
        } else if (colorAndNameMap.containsKey(3) && colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc123");
        }
        //一级区县内容
        StringBuilder country1 = new StringBuilder();
        //二级区县内容
        StringBuilder country2 = new StringBuilder();
        //三级区县内容
        StringBuilder country3 = new StringBuilder();

        List<ColorAndNameDto> colorAndNameDtoListAll = new ArrayList<>();
        if (colorAndNameMap.containsKey(0)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(0);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country1.append(colorAndNameDto.getCountry()).append(",");
            }
            country1.deleteCharAt(country1.length() - 1);
        }
        if (colorAndNameMap.containsKey(1)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(1);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country2.append(colorAndNameDto.getCountry()).append(",");
            }
            country2.deleteCharAt(country2.length() - 1);

        }
        if (colorAndNameMap.containsKey(2)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(2);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country3.append(colorAndNameDto.getCountry()).append(",");
            }
            country3.deleteCharAt(country3.length() - 1);
        }
        //替换正文内容
        docType = docType.replace("[一级区县]", country3.toString());
        docType = docType.replace("[二级区县]", country2.toString());
        docType = docType.replace("[三级区县]", country1.toString());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日HH时");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyyMM");
        Date date1 = sdf.parse(date);
        docType = docType.replace("[发布时间]",sdf1.format(date1));
        docType = docType.replace("[批号]",String.valueOf(issueNum));
        docType = docType.replace("[预警起报点]",sdf3.format(date1)+timeChar+"时");
        docType = docType.replace("[预警时长]",String.valueOf(nTimes));
        docType = docType.replace("[预警时效]",sdf3.format(date1)+timeChar+"时起"+nTimes+"小时");
        //设置点集合区县内容
        DzWarning dzWarning = new DzWarning();
        dzWarning.setPos(posStr);
        dzWarning.setGradearea3(country1.toString());
        dzWarning.setGradearea4(country2.toString());
        dzWarning.setGradearea5(country3.toString());
        //解析地理分析数据
        List<Object> layerObjectList = new ArrayList<>();
        if (StringUtils.isNotBlank(dlData) && StringUtils.isNotBlank(layerName)) {
            try {
                List<LayerRcoDto> LayerRcoDtoList = JSON.parseArray(dlData, LayerRcoDto.class);
                Class layerClass = getLayerClass(layerName);
                for (LayerRcoDto layerRcoDto : LayerRcoDtoList) {
                    JSONObject rcoValObject = (JSONObject) layerRcoDto.getRcoValObject();
                    Object javaObject = JSON.toJavaObject(rcoValObject, layerClass);
                    layerObjectList.add(javaObject);
                }
            } catch (Exception e) {
                System.err.println("地理分析数据解析错误");
            }
        }

        //生成文档
        try (
                InputStream templateInputStream = new FileInputStream(templatePath);
                OutputStream targetOutputStream = new FileOutputStream(targetPath);
                XWPFDocument document = new XWPFDocument(templateInputStream);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ByteArrayOutputStream byteArrayOutputStream1 = new ByteArrayOutputStream();
                ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream()
        ) {
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            //段落替换
            String[] placeholders = new String[]{"[文件号]", "[签发人1]", "[签发人2]", "[时间1]", "[预警内容]"};
            //替换内容
            String[] replacements = new String[]{String.valueOf(issueNum), userName, userName, sdf3.format(date1)+timeChar+"时", docType};

            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                String text = paragraph.getText();

                replaceTextInParagraph(paragraph, placeholders, replacements);

                //插入图片
                if (StringUtils.isNotBlank(text) && text.contains("[图1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFParagraph newPara = document.insertNewParagraph(cursor);
                    newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                    XWPFRun newParaRun = newPara.createRun();
                    for (MultipartFile image : images) {
                        //插入图片
                        newParaRun.addPicture(image.getInputStream(), XWPFDocument.PICTURE_TYPE_PNG, "image.png,", Units.toEMU(300), Units.toEMU(380));
                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
                //插入预警区表格
                if (StringUtils.isNotBlank(text) && text.contains("[表1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFTable table = document.insertNewTbl(cursor);
                    //添加表头
                    XWPFTableRow row_0 = table.getRow(0);
                    row_0.getCell(0).setText("市州");
                    row_0.addNewTableCell().setText("乡镇");
                    row_0.addNewTableCell().setText("预警等级");
                    colorAndNameDtoListAll.forEach(country -> {
                        XWPFTableRow dataRow = table.createRow();
                        dataRow.getCell(0).setText(country.getCounty());
                        dataRow.getCell(1).setText(country.getCountry());
                        dataRow.getCell(2).setText(country.getColor());
                    });
                    setTableLocation(table, "center");
                    setCellLocation(table, "CENTER", "center");
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
                //插入地理分析数据表格
                if (layerObjectList.size() > 0 && StringUtils.isNotBlank(text) && text.contains("[预警信息表]")) {
                    System.out.println("插入地理分析表格数据");
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFTable table = document.insertNewTbl(cursor);
                    //插入图层表格数据
                    insertTablaLayerData(layerName,layerObjectList,table);
                    setTableLocation(table, "center");
                    setCellLocation(table, "CENTER", "center");
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));

                }
            }
            // 将生成的文档保存到输出文件
             document.write(targetOutputStream);

            //获取文档名称

            String productName = "地质灾害预警文档第"+issueNum+"期"+sdf4.format(date1)+".docx";
            //插入地质预警表数据

            dzWarning.setDatechar(sdf.parse(sdf2.format(date1)));
            dzWarning.setTimechar(timeChar);
            dzWarning.setNtimes(nTimes);
            dzWarning.setState(3);
            dzWarning.setFirst(userName);
            dzWarning.setSecond(userName);
            dzWarning.setThird(userName);
            dzWarning.setIsrelease(0);
            dzWarning.setShflag(0);
            dzWarning.setForetype(0);
            dzWarning.setWarningtype(sXType);
            dzWarning.setDocpath(productName);
            dzWarning.setWarn_result(docType);
            dzWarningMapper.insert(dzWarning);
            //保存基本产品表数据
            BaseProduct baseProduct = new BaseProduct();
            baseProduct.setProductname(productName);
            baseProduct.setProducttype(yjType+sXType);
            baseProduct.setForecasttime(date1);
            baseProduct.setMaketime(new Date());
            baseProduct.setBindid(dzWarning.getDocid());
            baseProduct.setMaker(userName);
            baseProductMapper.insert(baseProduct);
            byte[] buffer = new byte[1024];
            int bytesRead;
            FileInputStream inputStream = new FileInputStream(targetPath);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();

            wordToPdf(targetPath, targetPdfPath);
            //保存到mongodb库中
            // HyDocFile hyDocFile = new HyDocFile();
            // hyDocFile.setData(byteArray);
            // hyDocFile.setTable_name("base_product");
            // hyDocFile.setId(String.valueOf(baseProduct.getId()));
            //mongoTemplate.save(hyDocFile);
            Map<String, Object> map1 = new HashMap<String, Object>();
            map1.put("id", String.valueOf(dzWarning.getDocid()));
            map1.put("data", byteArray);
            map1.put("table_name", "base_product");
            map1.put("collectionName", "doc_file");
            ms.insertData(map1);

          //pdf入库
            byte[] buffer1 = new byte[1024];
            int bytesRead1 ;
            FileInputStream inputStream1 = new FileInputStream(targetPdfPath);
            while ((bytesRead1 = inputStream1.read(buffer1)) != -1) {
                byteArrayOutputStream1.write(buffer1, 0, bytesRead1);
            }

            byte[] bytes = byteArrayOutputStream1.toByteArray();
            Map<String, Object> map2 = new HashMap<String, Object>();
            map2.put("id", String.valueOf(baseProduct.getId()));
            map2.put("data", bytes);
            map2.put("table_name", "base_product");
            map2.put("collectionName", "pdf_file");
            map2.put("advCode", "451027");
            ms.insertData(map2);
             //图片
            for (MultipartFile image : images) {
                //插入图片
                InputStream inputStream2 = image.getInputStream();
                byte[] buffer2 = new byte[1024];
                int bytesRead2;
                while ((bytesRead2 = inputStream2.read(buffer2)) != -1) {
                    byteArrayOutputStream2.write(buffer2, 0, bytesRead2);
                }
                byte[] bytes2 = byteArrayOutputStream2.toByteArray();
                Map<String, Object> map3 = new HashMap<String, Object>();
                map3.put("id", String.valueOf(baseProduct.getId()));
                map3.put("data", bytes2);
                map3.put("table_name", "base_product");
                map3.put("collectionName", "image_file");
                map3.put("advCode", "451027");
                ms.insertData(map3);
            }

            // 设置前端响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", "地灾预警文档.docx");
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(byteArray.length);
//            wordToPdf(targetPath,targetPdfPath);
            return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("文档生成失败");
        }
        return null;

    }




}
